package com.xu.demob.controller;


import com.baidu.aip.util.Base64Util;
import com.xu.demob.service.BaiduOcrService;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
//import com.google.gson.*;
import java.util.*;
import java.util.regex.*;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.logging.Logger;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.imageio.ImageIO;


@RestController
@RequestMapping("/api")
public class OcrController {

    private static final Logger LOGGER = Logger.getLogger(OcrController.class.getName());

    @Autowired
    private  BaiduOcrService baiduOcrService;

    /**
     * 通过百度OCR服务识别车牌信息。
     *
     * @param imageFile 上传的图片文件，包含待识别的车牌。
     * @return 返回识别出的车牌信息。
     */
    @PostMapping("/recognize-license-plate")
    public ResponseEntity<String> recognizeLicensePlate(@RequestParam("image") MultipartFile imageFile) {
        try {
            // 将上传的文件保存到临时目录
//            File file = new File(System.getProperty("java.io.tmpdir") + "/" + imageFile.getOriginalFilename());
//            imageFile.transferTo(file);
            byte[] bytes = imageFile.getBytes();

            // 记录文件大小
            LOGGER.info("File size: " + bytes.length + " bytes");

            // 将字节数组编码为Base64字符串
            String base64String = Base64.getEncoder().encodeToString(bytes);

            // 记录文件上传成功的日志
//            LOGGER.info("File uploaded: " + file.getAbsolutePath());

            String filePath = "D:/home/testwork/demoB/src/main/java/com/xu/demob/controller/carBase64.txt";
            String base64String2 = readBase64FromFile(filePath);

            // 调用百度OCR服务识别车牌信息
            String result = baiduOcrService.recognizeLicensePlate(base64String2);

            // 删除临时文件
//            file.delete();
//
            // 返回识别结果
            return ResponseEntity.ok(result);
        } catch (IOException e) {
            // 记录文件上传失败的日志
            LOGGER.severe("File upload failed: " + e.getMessage());
            // 返回文件上传失败的响应
            return ResponseEntity.status(500).body("File upload failed: " + e.getMessage());
        }
    }

    /**
     * 通过百度OCR服务识别身份证信息。
     *
     * @param imageFile  上传的身份证图片文件。
     * @param idCardSide 身份证的正反面，用于指定OCR服务识别哪一面。
     * @return 识别结果以字符串形式返回。
     * @throws IOException 如果文件上传或删除失败。
     */
    @PostMapping("/recognize-id-card")
    public ResponseEntity<String> recognizeIdCard(@RequestParam("image") MultipartFile imageFile,
                                                  @RequestParam("side") String idCardSide) {
        try {
            // 将上传的文件保存到临时目录
            File file = new File(System.getProperty("java.io.tmpdir") + "/" + imageFile.getOriginalFilename());
            imageFile.transferTo(file);

            // 记录文件上传成功的日志
            LOGGER.info("File uploaded: " + file.getAbsolutePath());

            // 调用百度OCR服务识别身份证信息
            String result = baiduOcrService.recognizeIdCard(file.getAbsolutePath(), idCardSide);

            // 删除临时文件
            file.delete();

            // 返回识别结果
            return ResponseEntity.ok(result);
        } catch (IOException e) {
            // 记录文件上传失败的日志
            LOGGER.severe("File upload failed: " + e.getMessage());

            // 返回文件上传失败的响应
            return ResponseEntity.status(500).body("File upload failed: " + e.getMessage());
        }
    }

    /**
     * 通过自定义模板OCR服务识别图片中的内容
     *
     * @param imageFile    上传的包含待识别内容的图片文件。
     * @param templateSign 自定义模板的签名。
     * @return 识别结果的字符串形式。
     * @throws IOException 如果文件上传失败。
     */
    @PostMapping("/recognize-custom")
    public ResponseEntity<String> recognizeCustomTemplate(@RequestParam("image") MultipartFile imageFile,
                                                          @RequestParam("templateSign") String templateSign) throws IOException {
        try {
            // 将上传的文件保存到临时目录
            File file = new File(System.getProperty("java.io.tmpdir") + "/" + imageFile.getOriginalFilename());
            imageFile.transferTo(file);

            // 记录文件上传成功的日志
            LOGGER.info("File uploaded: " + file.getAbsolutePath());


            // 调用自定义模板OCR接口识别内容
            String result = baiduOcrService.recognizeCustomTemplate(file.getAbsolutePath(), templateSign);

            // 删除临时文件
            file.delete();

            // 返回识别结果
            return ResponseEntity.ok(result);
        } catch (IOException e) {
            // 记录文件上传失败的日志
            LOGGER.severe("File upload failed: " + e.getMessage());

            // 返回文件上传失败的响应
            return ResponseEntity.status(500).body("File upload failed: " + e.getMessage());
        }
    }

    @PostMapping("/recognize-custom-base")
    public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file, @RequestParam("templateSign") String templateSign) {
        try {
            // 获取文件的字节数组
            byte[] bytes = file.getBytes();

            // 记录文件大小
            LOGGER.info("File size: " + bytes.length + " bytes");

            // 将字节数组编码为Base64字符串
            String base64String = Base64.getEncoder().encodeToString(bytes);
            System.out.println(base64String);

            String filePath = "D:/home/testwork/demoB/src/main/java/com/xu/demob/controller/base64.txt";
            String base64String2 = readBase64FromFile(filePath);

            byte[] bytes2 = Base64.getDecoder().decode(base64String);

            // 记录Base64编码后的字符串长度
            LOGGER.info("Base64 string length: " + base64String.length());

            // 调用OCR识别服务
            String result = baiduOcrService.recognizeCustomTemplate2(bytes2, templateSign);

            // 返回识别结果
            return ResponseEntity.ok(result);
        } catch (IOException e) {
            LOGGER.severe("File upload failed: " + e.getMessage());
            return ResponseEntity.status(500).body("File upload failed: " + e.getMessage());
        } catch (Exception e) {
            LOGGER.severe("OCR service error: " + e.getMessage());
            return ResponseEntity.status(500).body("OCR service error: " + e.getMessage());
        }
    }

    public static String readBase64FromFile(String filePath) throws IOException {
        return new String(Files.readAllBytes(Paths.get(filePath)));
    }


    @PostMapping("/recognize-numbers")
    public String numbers(@RequestParam("file") MultipartFile file) throws IOException {
        // 获取文件的字节数组
        byte[] bytes = file.getBytes();
        String base64Image = Base64.getEncoder().encodeToString(bytes);

        // 解码 Base64 字符串
        byte[] imageBytes = Base64.getDecoder().decode(base64Image);
        BufferedImage image = ImageIO.read(new ByteArrayInputStream(imageBytes));

        // 调用OCR识别服务
        JSONObject ocrResult = baiduOcrService.numbers(bytes);
        JSONArray wordsResult = ocrResult.getJSONArray("words_result");

        // 定义图片的中心区域范围，假设图像大小已知为1000x1000
        // 示例：中心区域是图像的中心位置的200x200像素
//        int imageWidth = 1000;  // 假设图片宽度为1000
//        int imageHeight = 1000;  // 假设图片高度为1000
        // 获取图片的宽度和高度
        int imageWidth = image.getWidth();
        int imageHeight = image.getHeight();

        // 图片中心点
        int centerX = imageWidth / 2;
        int centerY = imageHeight / 2;

        for (int i = 0; i < wordsResult.length(); i++) {
            JSONObject wordInfo = wordsResult.getJSONObject(i);
            JSONObject location = wordInfo.getJSONObject("location");

            // 检查这个识别结果是否在我们指定的中心位置范围附近
            if (isNearCenter(location, centerX, centerY)) {
                return wordInfo.getString("words"); // 返回符合条件的数字
            }
        }

        return "No matching number found";  // 如果没有找到符合条件的数字，则返回此信息
    }

    /**
     * 判断给定位置是否接近指定中心点
     *
     * @Author: xu
     * @param location 位置信息的JSON对象，包含top、left、width和height属性
     * @param centerX 期望的中心点X坐标
     * @param centerY 期望的中心点Y坐标
     * @return 如果给定位置的中心点在指定中心点的阈值范围内，则返回true，否则返回false
     */
    private boolean isNearCenter(JSONObject location, int centerX, int centerY) {
        // 获取位置的上边界和左边界
        int locTop = location.getInt("top");
        int locLeft = location.getInt("left");
        // 获取位置的宽度和高度
        int locWidth = location.getInt("width");
        int locHeight = location.getInt("height");

        // 计算位置的中心点
        int locCenterX = locLeft + locWidth / 2;
        int locCenterY = locTop + locHeight / 2;

        // 设置一个阈值，例如 100 像素以内算作靠近中心
        int threshold = 100;
        // 判断位置的中心点是否在指定中心点的阈值范围内
        return Math.abs(locCenterX - centerX) <= threshold && Math.abs(locCenterY - centerY) <= threshold;
    }
    @PostMapping("/recognize-new")
    public ResponseEntity<Map>  recognizeTable(@RequestParam("file") MultipartFile file) throws IOException {
        byte[] bytes = file.getBytes();

        String base64String = Base64.getEncoder().encodeToString(bytes);
        // 调用OCR识别服务
        String ocrResult = baiduOcrService.table(base64String);
        //把ocrResult中所有的 /n去掉
        String ocrResult1 = ocrResult.replaceAll("\n", "");
        JSONObject jsonObject = new JSONObject(ocrResult1);
        //组装数据
        Map<String, String> stringStringMap = parseJsonToMap(jsonObject,base64String);

        // 输出结果
//        System.out.println(new Gson().toJson(result));
        //替换key的名
        Map<String, String> stringStringMap1 = processOcrResult(stringStringMap);
        return ResponseEntity.ok(stringStringMap1);
    }

    private  Map<String, String> parseJsonToMap(JSONObject jsonObject,String base64String) {
        // 提取 tables_result
        JSONArray tablesResult = jsonObject.getJSONArray("tables_result");

        // 定义一个 map 来存储解析后的数据
        Map<String, String> resultMap = new LinkedHashMap<>();

        // 定义一个计数器来跟踪"联系电话"出现的次数
        int contactCounter = 0;

        // 检测是否提取到了 number
        boolean hasNumber = false;

        // 遍历 tables_result 的每一个元素
        for (int i = 0; i < tablesResult.length(); i++) {
            JSONObject tableObject = tablesResult.getJSONObject(i);
            JSONArray bodyArray = tableObject.getJSONArray("body");

            // 用来存储每一行的单元格
            List<String> rowWords = new ArrayList<>();

            // 提取 header 部分的编号
            JSONArray header = tableObject.getJSONArray("header");
            for (int o = 0; o < header.length(); o++) {
                String headerWords = header.getJSONObject(o).getString("words");
                if (headerWords.startsWith("No.")) {
                    resultMap.put("number", headerWords.replace("No.", ""));
                    hasNumber = true; // 找到编号，标记为 true
                    break;
                }
            }

            // 遍历每一行
            for (int j = 0; j < bodyArray.length(); j++) {
                JSONObject cellObject = bodyArray.getJSONObject(j);
                String words = cellObject.getString("words").replace("\n", "");

                // 存储每个单元格的文字
                rowWords.add(words);
            }

            // 每一行的第一个单元格为k，后面的单元格为v
            for (int k = 0; k < rowWords.size(); k += 2) {
                String key = rowWords.get(k);
                String value = (k + 1 < rowWords.size()) ? rowWords.get(k + 1) : "";

                // 如果当前key是"备注"，解析内容
                if (key.equals("备注")) {
                    extractRemarks(value, resultMap);
                }
                // 处理"联系电话"字段
                else if (key.equals("联系电话")) {
                    if (contactCounter == 0) {
                        resultMap.put("货主联系电话", value);
                    } else if (contactCounter == 1) {
                        resultMap.put("承运人联系电话", value);
                    }
                    contactCounter++; // 每次处理完一个联系电话，计数器加1
                }
                else {
                    resultMap.put(key, value);
                }
            }

        }

        // 如果没有找到编号，调用通用文字识别接口
        if (!hasNumber) {
            String generalOcrResult = baiduOcrService.generalBasic(base64String); // 调用百度OCR通用文字识别接口
            String number = extractNumberFromGeneralOcr(generalOcrResult);
            if (number != null) {
                resultMap.put("number", number);
            }
        }

        // 输出结果
        resultMap.forEach((key, value) -> {
            System.out.println(key + " -> " + value);
        });
        return resultMap;
    }

    // 从备注内容中提取出 车牌号, 贩运主体, 贩运主体手机号 并加入到map中
    public static void extractRemarks(String remarks, Map<String, String> resultMap) {
        // 修改后的正则表达式，匹配车牌号(运载工具牌号)、贩运主体、贩运主体手机号
//        Pattern licensePlatePattern = Pattern.compile("(车牌号|运载工具牌号)：([\\w\\d]+)");
//        Pattern carrierPattern = Pattern.compile("贩运主体：([^贩运主体手机号]+)");  // 捕获不包含"贩运主体手机号"的内容
//        Pattern phonePattern = Pattern.compile("贩运主体手机号：([\\d]+)");


        Pattern licensePlatePattern = Pattern.compile("(车牌号|运载工具牌号)：([^贩运主体]+)");
        Pattern carrierPattern = Pattern.compile("贩运主体：([^贩运主体手机号]+)");
        Pattern phonePattern = Pattern.compile("贩运主体手机号：([\\d]+)");

        Matcher licensePlateMatcher = licensePlatePattern.matcher(remarks);
        Matcher carrierMatcher = carrierPattern.matcher(remarks);
        Matcher phoneMatcher = phonePattern.matcher(remarks);

        // 提取车牌号或运载工具牌号
        if (licensePlateMatcher.find()) {
            String licensePlateValue = licensePlateMatcher.group(2).trim().replaceAll("】", ""); // 去除】符号
            resultMap.put(licensePlateMatcher.group(1), licensePlateValue);
        }

        // 提取贩运主体
        if (carrierMatcher.find()) {
            resultMap.put("贩运主体", carrierMatcher.group(1).trim());
        }

        // 提取贩运主体手机号
        if (phoneMatcher.find()) {
            resultMap.put("贩运主体手机号", phoneMatcher.group(1));
        }
    }

    public static Map<String, String> processOcrResult(Map<String, String> ocrData) {

        Map<String, String> keyMapping = new LinkedHashMap<>();

            keyMapping.put("牲畜耳标号", "earTagEntry");
            keyMapping.put("承运人", "wensHaulier");
            keyMapping.put("联系电话", "wensHaulierPhonen");
            keyMapping.put("车牌号", "wensLicenseNumber");
            keyMapping.put("用途", "wensPurpose");
            keyMapping.put("到达地点", "wensDestination");
            keyMapping.put("启运地点", "wensStartingpoint");
            keyMapping.put("数量及单位", "wensNumandunit");
            keyMapping.put("动物种类", "wensAnimalType");
            keyMapping.put("货主", "wensCargoOwner");
            keyMapping.put("number", "number");
        Map<String, String> result = new LinkedHashMap<>();

        // 遍历ocrData，检查是否有对应的key转换
        for (Map.Entry<String, String> entry : ocrData.entrySet()) {
            String chineseKey = entry.getKey().trim();
            String value = entry.getValue().replaceAll("\\n", ""); // 去掉换行符

            if (keyMapping.containsKey(chineseKey)) {
                String englishKey = keyMapping.get(chineseKey);
                result.put(englishKey, value);
            }
        }
        return result;
    }



    // 从百度OCR通用识别结果中提取 "No." 编号
    private static String extractNumberFromGeneralOcr(String generalOcrResult) {
        JSONObject generalOcrJson = new JSONObject(generalOcrResult);
        JSONArray wordsResult = generalOcrJson.getJSONArray("words_result");

        for (int i = 0; i < wordsResult.length(); i++) {
            String words = wordsResult.getJSONObject(i).getString("words");
            if (words.startsWith("No.")) {
                return words.replace("No.", "").trim(); // 返回编号部分
            }
        }
        return null; // 没有找到编号时返回 null
    }
}


